<template>
    <uxCollapse class="header-search-el">
        <template slot="suffix">
            <ux-btn-group
                :isCheckPermissions="isCheckPermissions"
                :btns="btnList"
                :data="btnsData"
                :slotList.sync="btnSlotList"
                class="box-row box-center-end"
            >
                <template v-slot:[item]="data" v-for="item in btnSlotList">
                    <slot :name="item" v-bind="data"></slot>
                </template>
            </ux-btn-group>
        </template>
        <!-- 使用v-show是为了避免需要设值数据时找不到对象 -->
        <ux-form
            inline
            ref="form"
            v-show="isSearch"
            v-bind="$attrs"
            v-on="$listeners"
            :labelWidth="labelWidth"
            :slotList.sync="formSlotList"
        >
            <template v-slot:[item]="data" v-for="item in formSlotList">
                <slot :name="item" v-bind="data"></slot>
            </template>
        </ux-form>
    </uxCollapse>
</template>
<script >
import { defaults, concat, isEmpty, max } from "lodash";
import { checkCondition } from "@/utils";
import { mixinObserver } from "@/components/mixin/Observer";
import uxForm from "@/components/form";
import uxBtnGroup from "@/components/btn/group";
import uxCollapse from "@/components/collapse";
/**
 *
 * 列表查询头组件，可以根据传入关联数据动态控制具体按钮显示隐藏
 */
export default {
    name: "UxHeaderSearch",

    mixins: [mixinObserver],

    components: { uxForm, uxBtnGroup, uxCollapse },

    props: {
        // 点击清空按钮后是否执行查询
        isClearSearch: {
            type: Boolean,
            default: true
        },
        // 是否必须检查权限
        isCheckPermissions: {
            type: Boolean,
            default: true
        },
        // 设置为true时等同form组件的labelWidth:'auto'效果
        // 因为form表单的labelWidth:'auto'在视图销毁时有bug，所以这里自己写代码实现类型效果
        isAutoWidth: {
            type: Boolean,
            default: true
        },
        // 按钮组关联数据
        btnsData: {
            type: Object
        },
        // 查询按钮配置
        searchBtn: {
            type: Object
        },
        // 清空按钮配置
        clearBtn: {
            type: Object
        },
        // 按钮组
        // isDrop: true, 是否在更多按钮组
        // sort:1, 排序值，默认为1
        // label: "详情", 文本
        // class: "btn-blue", 样式
        // condition: ["permissionsData.info"], 校验条件
        // param: "winInfo", 点击时传递的第二个参数
        // handleClick: (this as any).onInfoClick 点击时触发方法，第一个参数为 data
        btns: {
            type: Array,
            default: function () {
                return [];
            }
        }
    },

    data() {
        return {
            // 查询按钮默认配置
            // 可覆盖，请勿覆盖handleClick配置
            defaultSearchBtn: {
                label: "查询",
                class: "btn-blue",
                icon: "el-icon-search",
                type: "primary",
                handleClick: this.onSearchClick
            },
            // 清空按钮默认配置
            // 可覆盖，请勿覆盖handleClick配置
            defaultClearBtn: {
                label: "重置",
                class: "btn-clear",
                 icon: "el-icon-refresh",
                handleClick: this.onClearClick
            },
            labelWidth: null,
            formSlotList: [],
            btnSlotList: []
        };
    },

    computed: {
        // 查询按钮最终配置
        searchBtnConfig() {
            return defaults(this.searchBtn, this.defaultSearchBtn);
        },
        // 是否显示查询模块
        isSearch() {
            const me = this,
                btnsData = me.btnsData;
            // 如果没有按钮数据，默认显示
            if (isEmpty(btnsData) && !me.isCheckPermissions) {
                return true;
            }
            // 根据按钮数据和校验配置确定是否显示
            return checkCondition(me.searchBtnConfig, btnsData);
        },
        // 清空按钮最终配置
        clearBtnConfig() {
            return defaults(this.clearBtn, this.defaultClearBtn);
        },
        // 最终按钮组配置
        btnList() {
            const me = this,
                btns = me.btns;
            return me.isSearch
                ? concat(me.searchBtnConfig, me.clearBtnConfig, btns)
                : btns;
        }
    },

    methods: {
        // 点击查询按钮时
        onSearchClick() {
            const me = this,
                form = me.getForm();
            // 验证表单
            form.validateForm().then((values) => {
                // 抛出查询事件
                me.$emit("search", values);
            });
        },
        // 点击清空按钮时
        onClearClick() {
            const me = this,
                form = me.getForm();
            // 重置表单校验状态
            // form.clearValidate();
            // 重置表单值
            form.resetFields();
            if (me.isClearSearch) {
                me.$nextTick(() => {
                    // 重新事件
                    me.onSearchClick();
                });
            }
        },
        // 获取form对象，用于执行form方法
        getForm() {
            return this.$refs.form;
        },
        /**
         * 设置表单默认值，并查询
         * @param {Object} v 默认值
         *
         */
        setDefaultValuesAndSearch(v) {
            const me = this,
                form = me.getForm();
            //  form.setDefaultValues(v);
            form.setDefaultValues(v);
            me.$nextTick(() => {
                me.onSearchClick();
            });
        },
        /**
         * @description 计算表单文本宽度
         *
         */
        adjustLayout() {
            const me = this;
            me.$nextTick(() => {
                const el = me.$el;
                if (el) {
                    // 因为form表单的labelWidth:'auto'有bug，所以这里自己写代码实现类型效果
                    if (me.isAutoWidth) {
                        // 获取表单dom
                        const formEl = me.$refs.form.$el;
                        // 查找表单所有的子组件的文本集合
                        const list = formEl.getElementsByClassName(
                            "el-form-item__label"
                        );
                        const widthList = [];
                        // 获取文本宽度集合
                        list.forEach((item) => {
                            widthList.push(item.clientWidth);
                        });
                        // 获取最大文本宽度
                        const maxNum = max(widthList);
                        if (maxNum > 0) {
                            // 设置文本宽度
                            me.labelWidth = maxNum + 5 + "px";
                        } else {
                            // 某些情况下（视图被隐藏）,没办法计算文本最大宽度，这个时候就通过观察模式来监听容器变化，以便重新计算
                            me.startObserver(formEl);
                        }
                    }
                }
            });
        }
    }
};
</script>